package com.mdd.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mdd.admin.service.IOrderMenuService;
import com.mdd.admin.validate.commons.PageValidate;
import com.mdd.admin.validate.order.OrderMenuSearchValidate;
import com.mdd.admin.validate.order.OrderMenuUpdateValidate;
import com.mdd.admin.vo.order.MenuMealVo;
import com.mdd.common.core.PageResult;
import com.mdd.common.entity.order.MenuMeal;
import com.mdd.common.entity.order.OrderMeal;
import com.mdd.common.entity.order.OrderMenu;
import com.mdd.common.mapper.order.MenuMealMapper;
import com.mdd.common.mapper.order.OrderMealMapper;
import com.mdd.common.mapper.order.OrderMenuMapper;
import com.mdd.common.util.*;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author shenjian
 * @createTime 2023年02月12日 12:32:00
 */
@Service
public class OrderMenuServiceImpl implements IOrderMenuService {


    @Resource
    OrderMenuMapper orderMenuMapper;

    @Resource
    OrderMealMapper orderMealMapper;

    @Resource
    MenuMealMapper menuMealMapper;

    @Override
    public PageResult<MenuMealVo> list(PageValidate pageValidate, OrderMenuSearchValidate searchValidate) {
        Integer pageNo = pageValidate.getPageNo();
        Integer pageSize = pageValidate.getPageSize();
        Page<MenuMeal> iPage = new Page<>();
        List<MenuMealVo> list = new ArrayList<>();
        OrderMenu orderMenu = this.orderMenuMapper.selectOne(new QueryWrapper<OrderMenu>()
                .eq("day", searchValidate.getDay())
                .last("limit 1"));
        if (orderMenu != null) {
            List<String> orderList = new ArrayList<>();
            orderList.add("seq");
            orderList.add("id");
            // 查询菜单关联的套餐
            iPage = this.menuMealMapper.selectPage(
                    new Page<>(pageNo, pageSize),
                    new QueryWrapper<MenuMeal>()
                            .orderByAsc(orderList)
                            .eq("is_delete", 0)
                            .eq("menu_id", orderMenu.getId())
            );
            List<Integer> mealIdList = iPage.getRecords().stream()
                    .map(MenuMeal::getMealId)
                    .collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(mealIdList)) {
                List<OrderMeal> meals = this.orderMealMapper.selectList(new QueryWrapper<OrderMeal>()
                        .in("id", mealIdList));
                Map<Integer, List<OrderMeal>> mealMap = meals.stream().collect(Collectors.groupingBy(OrderMeal::getId));

                for (MenuMeal menuMeal : iPage.getRecords()) {
                    MenuMealVo vo = new MenuMealVo();
                    final OrderMeal meal = mealMap.get(menuMeal.getMealId()).get(0);
                    BeanUtils.copyProperties(menuMeal, vo);
                    vo.setMealSn(meal.getSn());
                    vo.setMealName(meal.getMealName());
                    vo.setMealPic(meal.getMealPic());
                    vo.setMealDescribe(meal.getMealDescribe());
                    vo.setPrice(AmountUtils.changeF2Y(menuMeal.getPrice()));
                    vo.setPreferentialAmount(AmountUtils.changeF2Y(menuMeal.getPreferentialAmount()));
                    vo.setActualAmount(AmountUtils.changeF2Y(menuMeal.getPrice() - menuMeal.getPreferentialAmount()));
                    list.add(vo);
                }
            }
        }
        return PageResult.iPageHandle(iPage.getTotal(), iPage.getCurrent(), iPage.getSize(), list);
    }

    @Override
    public void submit(OrderMenuUpdateValidate updateValidate) {
        // 查询菜单是否创建
        OrderMenu orderMenu = this.orderMenuMapper.selectOne(new QueryWrapper<OrderMenu>()
                .eq("day", updateValidate.getDay())
                .last("limit 1"));
        List<MenuMeal> meals = new ArrayList<>();
        if(orderMenu == null) {
            // 如果菜单未创建，则新建菜单
            orderMenu = OrderMenu.builder()
                    .day(updateValidate.getDay())
                    .week(DateUtils.convertWeek(updateValidate.getDay()))
                    .status(0)
                    .createTime(TimeUtils.timestamp())
                    .build();
            this.orderMenuMapper.insert(orderMenu);
        } else {
            Assert.isFalse(orderMenu.getStatus() == 2, "菜单已失效，不能更新");
            // 如果菜单已创建，则查询菜单关联的套餐
            meals = this.menuMealMapper.selectList(new QueryWrapper<MenuMeal>()
                    .eq("menu_id", orderMenu.getId()));
        }
        List<MenuMealVo> mealList = updateValidate.getMealList();
        // 查询套餐
        final List<Integer> mealIds = mealList.stream().map(MenuMealVo::getMealId).collect(Collectors.toList());
        Assert.isTrue(mealIds.size() == this.orderMealMapper.selectCount(new QueryWrapper<OrderMeal>()
                .in("id", mealIds)
                .eq("is_delete", 0)), "套餐数据有问题");
        // 分组
        Map<Integer, List<MenuMeal>> mealMap = meals.stream().collect(Collectors.groupingBy(MenuMeal::getMealId));
        // 判断菜单状态
        // 状态 0: 未生效 可以新增、删除、修改套餐
        // 状态 1: 已生效 可以新增、修改套餐
        // 状态 2: 已失效 不能修改
        switch(orderMenu.getStatus()) {
            case 0 :
                // 新增、更新(包含删除)
                // 先删除数据库所有相关联的数据
                this.menuMealMapper.delete(new QueryWrapper<MenuMeal>()
                        .eq("menu_id", orderMenu.getId()));
                // 循环新增
                for (MenuMealVo vo : mealList) {
                    MenuMeal menuMeal = new MenuMeal();
                    List<MenuMeal> menuMeals = mealMap.get(vo.getMealId());
                    if (menuMeals != null && !menuMeals.isEmpty()) {
                        menuMeal = menuMeals.get(0);
                    }
                    menuMeal.setPrice(AmountUtils.changeY2F(vo.getPrice()));
                    menuMeal.setPreferentialAmount(AmountUtils.changeY2F(vo.getPreferentialAmount()));
                    menuMeal.setStock(vo.getStock());
                    menuMeal.setIsDelete(vo.getIsDelete());
                    menuMeal.setStatus(vo.getStatus());
                    menuMeal.setMenuId(orderMenu.getId());
                    menuMeal.setMealId(vo.getMealId());
                    menuMeal.setCreateTime(TimeUtils.timestamp());
                    menuMeal.setSeq(vo.getSeq());
                    menuMeal.setVersion(0);
                    this.menuMealMapper.insert(menuMeal);
                }
                break;
            case 1 :
                // 新增、更新(包含删除)
                for (MenuMealVo vo : mealList) {
                    MenuMeal menuMeal = new MenuMeal();
                    List<MenuMeal> menuMeals = mealMap.get(vo.getMealId());
                    boolean isExists = false;
                    if (!menuMeals.isEmpty()) {
                        menuMeal = menuMeals.get(0);
                        isExists = true;
                    }
                    Assert.isTrue ((AmountUtils.changeY2F(vo.getPrice()).equals(menuMeal.getPrice()) ||
                            AmountUtils.changeY2F(vo.getPreferentialAmount()).equals(menuMeal.getPreferentialAmount())),
                            "菜单已生效，套餐价格不能修改！");
                    menuMeal.setSeq(vo.getSeq());
                    menuMeal.setStock(vo.getStock());
                    menuMeal.setStatus(vo.getStatus());
                    if (isExists) {
                        menuMeal.setUpdateTime(TimeUtils.timestamp());
                        this.menuMealMapper.updateById(menuMeal);
                    } else {
                        menuMeal.setMenuId(orderMenu.getId());
                        menuMeal.setMealId(vo.getMealId());
                        menuMeal.setIsDelete(vo.getIsDelete());
                        menuMeal.setCreateTime(TimeUtils.timestamp());
                        menuMeal.setSeq(vo.getSeq());
                        menuMeal.setVersion(0);
                        this.menuMealMapper.insert(menuMeal);
                    }
                }
                break;
            default:
                break;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void setValid(Integer id) {
        OrderMenu orderMenu = this.orderMenuMapper.selectOne(new QueryWrapper<OrderMenu>()
                .eq("id", id));
        Assert.notNull(orderMenu, "菜单查询为空");
        List<OrderMenu> menuList = this.orderMenuMapper.selectList(new QueryWrapper<OrderMenu>()
                .eq("status", 1));
        for (OrderMenu menu : menuList) {
            menu.setStatus(2);
            menu.setUpdateTime(TimeUtils.timestamp());
            this.orderMenuMapper.updateById(menu);
        }
        orderMenu.setStatus(1);
        orderMenu.setUpdateTime(TimeUtils.timestamp());
        this.orderMenuMapper.updateById(orderMenu);
    }

    @Override
    public OrderMenu getValidMenu() {
        return orderMenuMapper.selectOne(new QueryWrapper<OrderMenu>()
                .orderByDesc("day")
                .eq("status", 1)
                .last("limit 1"));
    }


    @Override
    public OrderMenu getNextMenu() {
        LocalDate now = LocalDate.now();
        LocalDate nextDay = now.minusDays(-1);
        return orderMenuMapper.selectOne(new QueryWrapper<OrderMenu>()
                .eq("day", nextDay)
                .last("limit 1"));
    }

}
